package com.bice.dao;

import java.io.Serializable;
import java.util.List;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

@Repository
@Transactional
public class DaoImpl<T extends IEntity, PK extends Serializable> extends HibernateDaoSupport implements Dao<T, PK> {

    @Autowired
    public DaoImpl(SessionFactory sessionFactory) {
        super.setSessionFactory(sessionFactory);
    }

    @Transactional(readOnly=false)
    public PK save(T o) {
        return (PK) getHibernateTemplate().save(o);
    }

    @Transactional(readOnly=false)
    public void update(T o) {
        getHibernateTemplate().update(o);
    }

    @Transactional(readOnly=false)
    public void delete(T o) {
        getHibernateTemplate().delete(o);
    }

    @Transactional(readOnly=true)
    public T get(Class<T> type, PK id) {
        return (T) getHibernateTemplate().get(type, id);
    }
    
    @Transactional(readOnly=true)
    public T get(String name, PK id) {
        return (T) getHibernateTemplate().get(name, id);
    }

    @Transactional(readOnly=true)
    public T getUnique(DetachedCriteria criteria) {
        List<T> response = getHibernateTemplate().findByCriteria(criteria, 0, 1);
        if(response != null && !response.isEmpty()) {
            return response.get(0);
        }
        return null;
    }

    @Transactional(readOnly=true)
    public List<T> get(DetachedCriteria criteria) {
        return getHibernateTemplate().findByCriteria(criteria);
    }

    @Transactional(readOnly=true)
    public List<T> get(DetachedCriteria criteria, int firstResult, int maxResults) {
        return getHibernateTemplate().findByCriteria(criteria, firstResult, maxResults);
    }

    @Transactional(readOnly=true)
    public List<T> get(String hql, Object... values) {
        return getHibernateTemplate().find(hql, values);
    }

    @Transactional(readOnly=true)
    public List<T> getAll(Class<T> type) {
        return getHibernateTemplate().loadAll(type);
    }
    
    @Transactional(readOnly=true)
    public int count(DetachedCriteria criteria) {
        criteria.setProjection(Projections.rowCount());
        List response = getHibernateTemplate().findByCriteria(criteria);
        if(response != null && !response.isEmpty()) {
            return (Integer)response.get(0);
        }
        return 0;
    }

}